#ifndef __M_LOOPER_M__
#define __M_LOOPER_M__
#include "util.hpp"
#include "level.hpp"
#include "format.hpp"
#include "message.hpp"
#include "buffer.hpp"
#include "log.h"
#include "logger.hpp"
#include "sink.hpp"
#include <assert.h>
#include <atomic>
#include <fstream>
#include <condition_variable>
#include <vector>
#include <cstdarg>
#include <thread>
#include <mutex>
namespace log
{
    
    enum class AsyncType
    {
        ASYNC_SAFE,
        ASYNC_UNSAFE
    };
    using Functor = std::function<void(log::Buffer&)>;
    class AsyncLooper
    {
        public:
        AsyncLooper(const Functor& cb,log::AsyncType asyncType = log::AsyncType::ASYNC_UNSAFE)
        :_stop(false),
        _callback(cb),
        _asynType(asyncType),
        _thread(std::thread(&log::AsyncLooper::threadEntry,this))
        {
            ;
        }
        ~AsyncLooper()
        {
            stop();   
            std::cout << "Async_looper退出！"<<std::endl;
        }
        using ptr = std::shared_ptr<log::AsyncLooper>;
        void stop()
        {
            _stop = true; //将退出标志设置为true 
            _cond_con.notify_all(); //唤醒所有的工作线程
            _thread.join(); //等待工作线程的退出
        }
        void push(const char* data,size_t len)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            if(_asynType == log::AsyncType::ASYNC_SAFE)
            {
                _cond_pro.wait(lock,[&]()->bool
                {
                    //条件变量空值，若缓冲区剩余空间大小大于数据长度，则可以添加数据
                    return _con_buf.wirteablesize() > len   ;
                });
            }
            //能走下来代表满足了条件，可以向缓冲区添加数据
            _pro_buf.push(data,len);
            //唤醒消费者对缓冲区的数据进行处理
            _cond_con.notify_one();
        }
        private:
        //线程入口函数--对消费缓冲区中的数据进行处理，处理完毕后，初始化缓冲区，交换缓冲区  
        void threadEntry()
        {
            while(1)
            {
                //1. 判断缓冲区有没有数据，有则交换，无则阻塞,
                { //为互斥锁设置一个生命周期,当缓冲区交换完毕后就解锁
                    std::unique_lock<std::mutex> lock(_mutex);
                    //只有stop为true和生成者缓冲区为空的时候才退出
                    if(_stop && _pro_buf.empty()) break;
                    _cond_con.wait(lock,[&]()->bool
                    {
                        //当进程退出前或者生成缓冲区有数据的时候都向下走
                        return _stop || !_pro_buf.empty();
                    }); 
                }
                _pro_buf.swap(_con_buf);
                if(_asynType == log::AsyncType::ASYNC_SAFE)
                {
                    _cond_con.notify_all(); //唤醒所有的生成者
                }
                //2. 被唤醒后，对消费缓冲区进行数据处理
                _callback(_con_buf);
                //3. 初始化消费缓冲区
                _con_buf.reset();
            }
        }
        private:
        log::AsyncType _asynType;
        Functor _callback; //具体对缓冲区数据进行处理的回调函数，由异步工作器使用者传入
        private:
        std::atomic<bool> _stop; //工作器停止标志
        log::Buffer _pro_buf; //生成缓冲区
        log::Buffer _con_buf; //生成消费区
        std::mutex _mutex;
        std::condition_variable _cond_pro;
        std::condition_variable _cond_con;
        std::thread _thread; //异步工作器对应的工作线程
    };
}
#endif